﻿using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using Vepa.Shared;
using Vepa.Shared.Networking;
using Newtonsoft.Json;
using System.IO;
using log4net;

namespace Vepa.Server.Networking
{
    class ServerThread
    {
        #region Fields
        /// <summary>
        /// If set to true, the ServerThread is going to end after the current communication task is done
        /// </summary>
        public bool stop = false;
        //TODO: Add abort function (kill everything, no matter what it currently does).

        public bool running = false;
        public bool IsConnected(TcpClient client)
        {
            try
            {
                bool connected = !(client.Client.Poll(1, SelectMode.SelectRead) && client.Client.Available == 0);
                return connected;
            }
            catch
            {
                return false;
            }
        }

        private TcpClient connection = null;

        private static readonly ILog log = LogManager.GetLogger(typeof(ServerThread));
        #endregion

        #region Constructor
        /// <summary>
        /// Creates a new ServerThread instance
        /// </summary>
        /// <param name="connection"></param>
        public ServerThread(TcpClient connection)
        {
            log.Info("New client connected. IP Adress: " + ((IPEndPoint)connection.Client.RemoteEndPoint).Address.ToString());
            this.connection = connection;
           
            new Thread(new ThreadStart(doCommunication)).Start();
        }
        #endregion


        #region Methods
        private void doCommunication()
        {
            this.running = true;
            NetworkStream stream = connection.GetStream();
            StreamReader reader = new StreamReader(stream);
            StreamWriter writer = new StreamWriter(stream);

            
            while (IsConnected(this.connection) && !stop)
            {                
                if (connection.Available > 0)
                {
                    string request = reader.ReadLine();
                    Packet packet = JsonConvert.DeserializeObject<Packet>(request);
                    
                    switch (packet.Type)
                    {
                        case PacketType.VepaRequest:
                            var reqPacket = JsonConvert.DeserializeObject<VepaRequest>(request);                                                       
                            var resVepaPacket = new VepaResponse();
                            resVepaPacket.Vepa = VepaManager.getVepa(reqPacket.Version);
                            log.Info(string.Format("Sending Vepa version {0} to {1}", resVepaPacket.Vepa.Info.Version, ((IPEndPoint)connection.Client.RemoteEndPoint).Address.ToString()));
                            writer.Write(JsonConvert.SerializeObject(resVepaPacket, Formatting.Indented));                       
                            writer.Flush();                            
                            break;

                        case PacketType.ListRequest:
                            var resListPacket = new ListResponse();
                            resListPacket.List = VepaManager.getAllVepaInfos();
                            log.Info(string.Format("Sending List to {0}", ((IPEndPoint)connection.Client.RemoteEndPoint).Address.ToString()));
                            writer.Write(JsonConvert.SerializeObject(resListPacket, Formatting.Indented));
                            writer.Flush();
                            break;
                    }
                }
            }


            log.Info("Client disconnected. IP Adress: " + ((IPEndPoint)connection.Client.RemoteEndPoint).Address.ToString());
            stream.Close();
            stream.Dispose();
            reader.Dispose();
            writer.Dispose();
        }
        #endregion

    }
}
